#include "ConnectNPlayer.h"
#include <cstdlib>
#include <iostream>

using std::cerr;

ConnectNPlayer::ConnectNPlayer(int height1, int width1, int numToWin1, int debug1) {
	height = height1;
	width = width1;
	numToWin = numToWin1;
	debug = debug1;

	heights = new int[width];
	for(int x=0; x<width; x++)
		heights[x]=0;
	board = new bool*[width];
	for(int x = 0; x < width; x++)
		board[x] = new bool[height];
}

int ConnectNPlayer::getMove() {
	int move = calcMove();
	bool isEnd = isTerminateState(move,true);
	addDib(move, true);
	if (debug) {
		printBoard();
		if (isEnd) {
			cerr <<"AGENT WON!";
			exit(0);
		}
	}
	return move;
}

void ConnectNPlayer::setMove(int move)  {
	bool isEnd = isTerminateState(move,false);
	addDib(move, false);
	if (debug && isEnd) {
		cerr <<"AGENT LOSED!";
		exit(0);
	}
}

void ConnectNPlayer::addDib(int col, bool myTurn) {
	board[col][heights[col]] = myTurn;
	heights[col]++;
}

void ConnectNPlayer::removeDib(int col) {
	heights[col]--;
}

vector<int> ConnectNPlayer::getValidActions() {
    vector<int> cols (width);
    int k=0;
    for (int x=0;x<width;x++)
    	if (heights[x]<height) cols[k++] = x;
    cols.resize(k);
    return cols;
}

bool ConnectNPlayer::isTerminateState(int col, bool myTurn) {
    int x0 = col, y0 = heights[col];
    int yb, xl, xr, xbl, xtr, xtl, xbr, y;

    // b=bottom, t=top, l=left, r=right, e.g.:
    //  yb  = y-coordinate of the first symbol different from the given
    //        symbol, when walking downwards
    //  xbr = x-coordinate of the first symbol different from the given
    //        symbol, when walking diagonally to the right-top direction

    //Check downwards
    for (yb=y0-1; yb>=0 && board[x0][yb]==myTurn; yb--); //&& x>col-player->numToWin;
    if (y0-yb>=numToWin) return true;

    //Check Left to Right
    for (xl=x0-1; xl>=0    && heights[xl]>y0 && board[xl][y0]==myTurn; xl--); // && x>x0-player->numToWin
    for (xr=x0+1; xr<width && heights[xr]>y0 && board[xr][y0]==myTurn; xr++); // && x<x0+player->numToWin
    if (xr - xl > numToWin) return true;

    //Check bottom-left to top-right
    for (xbl=x0-1, y=y0-1; xbl>=0 && y>=0 && y<heights[xbl] && board[xbl][y]==myTurn; xbl--, y--);
    for (xtr=x0+1, y=y0+1; xtr<width      && y<heights[xtr] && board[xtr][y]==myTurn; xtr++, y++);
    if (xtr - xbl > numToWin) return true;

    //Check top-left to bottom-right
    for (xtl=x0-1, y=y0+1; xtl>=0            && y<heights[xtl] && board[xtl][y]==myTurn; xtl--, y++);
    for (xbr=x0+1, y=y0-1; xbr<width && y>=0 && y<heights[xbr] && board[xbr][y]==myTurn; xbr++, y--);
    if (xbr - xtl > numToWin) return true;

    return false;
}

void ConnectNPlayer::printBoard() {
	cerr<<"Board: "<<"\n";
	for(int y=height-1;y>=0;y--) {
		for(int x=0;x<width; x++) {
			char c = heights[x]>y ? board[x][y]? 'X': 'O' : '.';
			cerr<< c <<" ";
		}
		cerr<<"\n";
	}
}


//int ConnectNPlayer::calcMove() {return 1;};
